package cn.h8k.hj212.plugin.impl;

import cn.h8k.hj212.plugin.MonitoringFactorPlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 大气环境监测因子插件
 * 支持常见的大气污染物监测因子
 * 
 * @author HJ212 Team
 * @since 1.0
 */
public class AtmosphericFactorPlugin implements MonitoringFactorPlugin {
    
    private static final Logger logger = LoggerFactory.getLogger(AtmosphericFactorPlugin.class);
    
    private static final String PLUGIN_NAME = "AtmosphericFactorPlugin";
    private static final String PLUGIN_VERSION = "1.0.0";
    
    private final Map<String, FactorMetadata> factorMetadataMap = new HashMap<>();
    private boolean initialized = false;
    
    @Override
    public String getName() {
        return PLUGIN_NAME;
    }
    
    @Override
    public String getVersion() {
        return PLUGIN_VERSION;
    }
    
    @Override
    public List<String> getSupportedFactorCodes() {
        return Arrays.asList(
            "SO2-Rtd", "SO2-Min", "SO2-Hour", "SO2-Day",     // 二氧化硫
            "NOx-Rtd", "NOx-Min", "NOx-Hour", "NOx-Day",     // 氮氧化物
            "NO-Rtd", "NO-Min", "NO-Hour", "NO-Day",         // 一氧化氮
            "NO2-Rtd", "NO2-Min", "NO2-Hour", "NO2-Day",     // 二氧化氮
            "CO-Rtd", "CO-Min", "CO-Hour", "CO-Day",         // 一氧化碳
            "O3-Rtd", "O3-Min", "O3-Hour", "O3-Day",         // 臭氧
            "PM10-Rtd", "PM10-Min", "PM10-Hour", "PM10-Day", // PM10
            "PM25-Rtd", "PM25-Min", "PM25-Hour", "PM25-Day", // PM2.5
            "TSP-Rtd", "TSP-Min", "TSP-Hour", "TSP-Day",     // 总悬浮颗粒物
            "TVOC-Rtd", "TVOC-Min", "TVOC-Hour", "TVOC-Day"  // 总挥发性有机化合物
        );
    }
    
    @Override
    public List<String> getSupportedSystemTypes() {
        return Arrays.asList("31", "22"); // 大气环境污染源、空气质量监测
    }
    
    @Override
    public ValidationResult validateFactor(String factorCode, Object value, String flag) {
        if (!getSupportedFactorCodes().contains(factorCode)) {
            return ValidationResult.failure("不支持的监测因子: " + factorCode, "UNSUPPORTED_FACTOR");
        }
        
        FactorMetadata metadata = getFactorMetadata(factorCode);
        if (metadata == null) {
            return ValidationResult.failure("未找到监测因子元数据: " + factorCode, "METADATA_NOT_FOUND");
        }
        
        // 验证数据标识
        if (flag != null && !isValidFlag(flag)) {
            return ValidationResult.failure("无效的数据标识: " + flag, "INVALID_FLAG");
        }
        
        // 验证数值范围
        if (value instanceof Number) {
            double numValue = ((Number) value).doubleValue();
            
            if (metadata.getMinValue() != null && numValue < metadata.getMinValue()) {
                return ValidationResult.failure(
                    String.format("数值 %f 小于最小值 %f", numValue, metadata.getMinValue()), 
                    "VALUE_TOO_SMALL"
                );
            }
            
            if (metadata.getMaxValue() != null && numValue > metadata.getMaxValue()) {
                return ValidationResult.failure(
                    String.format("数值 %f 大于最大值 %f", numValue, metadata.getMaxValue()), 
                    "VALUE_TOO_LARGE"
                );
            }
        }
        
        return ValidationResult.success();
    }
    
    @Override
    public Object transformValue(String factorCode, Object value) {
        if (value == null) {
            return null;
        }
        
        FactorMetadata metadata = getFactorMetadata(factorCode);
        if (metadata == null) {
            return value;
        }
        
        // 根据精度要求格式化数值
        if (value instanceof Number && metadata.getPrecision() != null) {
            double numValue = ((Number) value).doubleValue();
            String format = "%." + metadata.getPrecision() + "f";
            return String.format(format, numValue);
        }
        
        return value;
    }
    
    @Override
    public FactorMetadata getFactorMetadata(String factorCode) {
        return factorMetadataMap.get(factorCode);
    }
    
    @Override
    public String getFactorUnit(String factorCode) {
        FactorMetadata metadata = getFactorMetadata(factorCode);
        return metadata != null ? metadata.getUnit() : null;
    }
    
    @Override
    public String getFactorDescription(String factorCode) {
        FactorMetadata metadata = getFactorMetadata(factorCode);
        return metadata != null ? metadata.getDescription() : null;
    }
    
    @Override
    public void initialize(Map<String, Object> config) {
        if (initialized) {
            logger.warn("插件 {} 已经初始化", getName());
            return;
        }
        
        logger.info("初始化大气环境监测因子插件");
        
        // 初始化监测因子元数据
        initializeFactorMetadata();
        
        initialized = true;
        logger.info("大气环境监测因子插件初始化完成");
    }
    
    @Override
    public void destroy() {
        if (!initialized) {
            return;
        }
        
        logger.info("销毁大气环境监测因子插件");
        factorMetadataMap.clear();
        initialized = false;
        logger.info("大气环境监测因子插件销毁完成");
    }
    
    /**
     * 初始化监测因子元数据
     */
    private void initializeFactorMetadata() {
        // 二氧化硫 (SO2)
        addFactorMetadata("SO2-Rtd", "二氧化硫实时值", "mg/m³", "二氧化硫浓度实时监测值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("SO2-Min", "二氧化硫分钟值", "mg/m³", "二氧化硫浓度分钟平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("SO2-Hour", "二氧化硫小时值", "mg/m³", "二氧化硫浓度小时平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("SO2-Day", "二氧化硫日均值", "mg/m³", "二氧化硫浓度日平均值", Double.class, 0.0, 1000.0, 3);
        
        // 氮氧化物 (NOx)
        addFactorMetadata("NOx-Rtd", "氮氧化物实时值", "mg/m³", "氮氧化物浓度实时监测值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("NOx-Min", "氮氧化物分钟值", "mg/m³", "氮氧化物浓度分钟平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("NOx-Hour", "氮氧化物小时值", "mg/m³", "氮氧化物浓度小时平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("NOx-Day", "氮氧化物日均值", "mg/m³", "氮氧化物浓度日平均值", Double.class, 0.0, 1000.0, 3);
        
        // 一氧化碳 (CO)
        addFactorMetadata("CO-Rtd", "一氧化碳实时值", "mg/m³", "一氧化碳浓度实时监测值", Double.class, 0.0, 100.0, 3);
        addFactorMetadata("CO-Min", "一氧化碳分钟值", "mg/m³", "一氧化碳浓度分钟平均值", Double.class, 0.0, 100.0, 3);
        addFactorMetadata("CO-Hour", "一氧化碳小时值", "mg/m³", "一氧化碳浓度小时平均值", Double.class, 0.0, 100.0, 3);
        addFactorMetadata("CO-Day", "一氧化碳日均值", "mg/m³", "一氧化碳浓度日平均值", Double.class, 0.0, 100.0, 3);
        
        // PM2.5
        addFactorMetadata("PM25-Rtd", "PM2.5实时值", "mg/m³", "PM2.5浓度实时监测值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("PM25-Min", "PM2.5分钟值", "mg/m³", "PM2.5浓度分钟平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("PM25-Hour", "PM2.5小时值", "mg/m³", "PM2.5浓度小时平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("PM25-Day", "PM2.5日均值", "mg/m³", "PM2.5浓度日平均值", Double.class, 0.0, 1000.0, 3);
        
        // PM10
        addFactorMetadata("PM10-Rtd", "PM10实时值", "mg/m³", "PM10浓度实时监测值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("PM10-Min", "PM10分钟值", "mg/m³", "PM10浓度分钟平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("PM10-Hour", "PM10小时值", "mg/m³", "PM10浓度小时平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("PM10-Day", "PM10日均值", "mg/m³", "PM10浓度日平均值", Double.class, 0.0, 1000.0, 3);
        
        // 臭氧 (O3)
        addFactorMetadata("O3-Rtd", "臭氧实时值", "mg/m³", "臭氧浓度实时监测值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("O3-Min", "臭氧分钟值", "mg/m³", "臭氧浓度分钟平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("O3-Hour", "臭氧小时值", "mg/m³", "臭氧浓度小时平均值", Double.class, 0.0, 1000.0, 3);
        addFactorMetadata("O3-Day", "臭氧日均值", "mg/m³", "臭氧浓度日平均值", Double.class, 0.0, 1000.0, 3);
    }
    
    /**
     * 添加监测因子元数据
     */
    private void addFactorMetadata(String code, String name, String unit, String description, 
                                 Class<?> valueType, Double minValue, Double maxValue, Integer precision) {
        FactorMetadata metadata = new FactorMetadata(code, name, unit, description, valueType, minValue, maxValue, precision);
        factorMetadataMap.put(code, metadata);
    }
    
    /**
     * 验证数据标识是否有效
     */
    private boolean isValidFlag(String flag) {
        return Arrays.asList("N", "D", "M", "S", "F", "C", "T", "B").contains(flag);
    }
}
